"""配置管理模块

负责加载、解析和管理项目配置文件。
"""

import os
import yaml
from typing import Dict, Any, Optional
from pathlib import Path


class Config:
    """配置管理器
    
    负责加载和管理YAML配置文件。
    """
    
    def __init__(self, config_path: Optional[str] = None):
        """初始化配置管理器
        
        Args:
            config_path: 配置文件路径，默认为 config/config.yaml
        """
        if config_path is None:
            # 默认配置文件路径
            project_root = Path(__file__).parent.parent.parent
            config_path = project_root / "config" / "config.yaml"
        
        self.config_path = Path(config_path)
        self._config_data = {}
        self._load_config()
    
    def _load_config(self):
        """加载配置文件"""
        try:
            if not self.config_path.exists():
                raise FileNotFoundError(f"配置文件不存在: {self.config_path}")
            
            with open(self.config_path, 'r', encoding='utf-8') as f:
                self._config_data = yaml.safe_load(f) or {}
            
            print(f"配置文件加载成功: {self.config_path}")
            
        except Exception as e:
            print(f"配置文件加载失败: {e}")
            # 使用默认配置
            self._config_data = self._get_default_config()
    
    def _get_default_config(self) -> Dict[str, Any]:
        """获取默认配置"""
        return {
            "model": {
                "name": "runwayml/stable-diffusion-v1-5",
                "device": "auto",
                "torch_dtype": "float16",
                "use_safetensors": True,
                "safety_checker": False
            },
            "generation": {
                "width": 512,
                "height": 512,
                "num_inference_steps": 50,
                "guidance_scale": 7.5,
                "scheduler": "ddim",
                "seed": None,
                "num_images": 1
            },
            "prompts": {
                "negative_prompt": "blurry, bad quality, distorted, deformed, low resolution, watermark"
            },
            "output": {
                "directory": "./outputs",
                "format": "png",
                "quality": 95,
                "filename_template": "{timestamp}_{prompt_hash}"
            },
            "optimization": {
                "enable_attention_slicing": True,
                "enable_cpu_offload": False,
                "enable_model_cpu_offload": False,
                "enable_xformers": False
            },
            "logging": {
                "level": "INFO",
                "file": "./logs/auto_video.log",
                "console": True
            }
        }
    
    def get(self, key: str, default: Any = None) -> Any:
        """获取配置值
        
        Args:
            key: 配置键，支持点号分隔的嵌套键，如 'model.name'
            default: 默认值
            
        Returns:
            配置值
        """
        keys = key.split('.')
        value = self._config_data
        
        try:
            for k in keys:
                value = value[k]
            return value
        except (KeyError, TypeError):
            return default
    
    def set(self, key: str, value: Any):
        """设置配置值
        
        Args:
            key: 配置键，支持点号分隔的嵌套键
            value: 配置值
        """
        keys = key.split('.')
        config = self._config_data
        
        # 创建嵌套字典结构
        for k in keys[:-1]:
            if k not in config:
                config[k] = {}
            config = config[k]
        
        config[keys[-1]] = value
    
    def get_model_config(self) -> Dict[str, Any]:
        """获取模型配置"""
        return self.get('model', {})
    
    def get_generation_config(self) -> Dict[str, Any]:
        """获取生成配置"""
        return self.get('generation', {})
    
    def get_output_config(self) -> Dict[str, Any]:
        """获取输出配置"""
        return self.get('output', {})
    
    def get_optimization_config(self) -> Dict[str, Any]:
        """获取优化配置"""
        return self.get('optimization', {})
    
    def save_config(self, output_path: Optional[str] = None):
        """保存配置到文件
        
        Args:
            output_path: 输出路径，默认为原配置文件路径
        """
        if output_path is None:
            output_path = self.config_path
        else:
            output_path = Path(output_path)
        
        try:
            # 确保目录存在
            output_path.parent.mkdir(parents=True, exist_ok=True)
            
            with open(output_path, 'w', encoding='utf-8') as f:
                yaml.dump(
                    self._config_data,
                    f,
                    default_flow_style=False,
                    allow_unicode=True,
                    indent=2
                )
            
            print(f"配置已保存到: {output_path}")
            
        except Exception as e:
            print(f"配置保存失败: {e}")
            raise
    
    def update_from_dict(self, config_dict: Dict[str, Any]):
        """从字典更新配置
        
        Args:
            config_dict: 配置字典
        """
        def deep_update(base_dict, update_dict):
            for key, value in update_dict.items():
                if isinstance(value, dict) and key in base_dict and isinstance(base_dict[key], dict):
                    deep_update(base_dict[key], value)
                else:
                    base_dict[key] = value
        
        deep_update(self._config_data, config_dict)
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return self._config_data.copy()
    
    def __str__(self) -> str:
        """字符串表示"""
        return yaml.dump(self._config_data, default_flow_style=False, allow_unicode=True)
    
    def __repr__(self) -> str:
        """对象表示"""
        return f"Config(config_path='{self.config_path}')"


# 全局配置实例
_global_config = None


def get_config(config_path: Optional[str] = None) -> Config:
    """获取全局配置实例
    
    Args:
        config_path: 配置文件路径
        
    Returns:
        配置实例
    """
    global _global_config
    
    if _global_config is None or config_path is not None:
        _global_config = Config(config_path)
    
    return _global_config


def reload_config(config_path: Optional[str] = None):
    """重新加载配置
    
    Args:
        config_path: 配置文件路径
    """
    global _global_config
    _global_config = Config(config_path)